sqlite3JoinType预定义连接类型,setJoinExpr设置连接类型,sqliteProcessJoin处理连接的表。
sqlite3JoinType函数:声明各种连接的类型。解析SELECT的连接操作符,再与该函数的连接类型对应起来。默认为内连接。
/ 注:这个函数为了确定连接的种类。根据连接的关键字处理连接的类 型。返回的整数代表连接的类型,而在处理关键字的过程中检测到错误,
那也返回连接类型,默认的连接类型是inner join连接。
/.
int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){/*传入分析树,三个令牌结构体.其中Parse是
** 语法解析器,分析截断文本,提出出单词。Token是子句的关键词*/
int jointype = 0;/*确定连接类型*/
Token *apAll[3];/*存放令牌*/
Token *p;/*声明一个临时令牌*/
/* 0123456789 123456789 123456789 123 */
static const char zKeyText[] =
"naturaleftouterightfullinnercross";/*存放字符数组,里面装的是连接类型,在下文中进行调用*/
static const struct {/*声明一个内部结构体*/
u8 i; /*zKeyText数组的起始关键字*/
u8 nChar; /*关键字的字符长度*/
u8 code; /*连接类型标记*/
} aKeyword[] = {/*声明一个关键字数组,根据下标和长度找到连接类型*/
/* natural */ { 0, 7, JT_NATURAL },/*下标从0开始,长度为7,自然连接*/
/* left */ { 6, 4, JT_LEFT|JT_OUTER },/*下标从6开始,长度为4,左连接或外连接*/
/* outer */ { 10, 5, JT_OUTER },/*下标从10开始,长度为5,外连接*/
/* right */ { 14, 5, JT_RIGHT|JT_OUTER },/*下标从14开始,长度为5,右连接或外连接*/
/* full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER },/*下标从19开始,长度为4,左连接或右连接或外连接,实质是个全连接*/
/* inner */ { 23, 5, JT_INNER },/*下标从23开始,长度为5,内连接*/
/* cross */ { 28, 5, JT_INNER|JT_CROSS },/*下标从28开始,长度为5,内连接或CROSS连接,实质是个CROSS join*/
};
static void setJoinExpr(Expr *p, int iTable){/*传入一个表达式,一个待连接的表*/
while( p ){
ExprSetProperty(p, EP_FromJoin);/*设置join中使用ON和USING子句*/
assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );/*判断表达式的属性,关于表达式的长度和剩余长度*/
ExprSetIrreducible(p);/*调试表达式,判读是否错误*/
p->iRightJoinTable = (i16)iTable;/*连接右表,即参数中传入的表*/
setJoinExpr(p->pLeft, iTable);/*递归调用自身*/
p = p->pRight;/*赋值表达式p为原来p的右子节点*/
}
}
sqliteProcessJoin函数:进行表之间的连接,生成一个中间结果集。
static int sqliteProcessJoin(Parse *pParse, Select *p){/*传入分析树,Select结构体*/
SrcList *pSrc; /*添加所有的表到表集合中*/
int i, j; /*循环参数*/
struct SrcList_item *pLeft; /*被添加的左表*/
struct SrcList_item *pRight; /*被添加的右表*/
pSrc = p->pSrc;/*赋值pSrc为Select结构体中FROM子句属性*/
pLeft = &pSrc->a[0];/*将表数组中第一个表作为左表*/
pRight = &pLeft[1];/*将表数组中第二个表作为右表*/